
#include "HttpServer.hpp"

#include "HttpSession.hpp"

#include <iostream>

// Report a failure
static void fail(boost::beast::error_code ec, char const* what) {
    std::cerr << what << ": " << ec.message() << "\n";
}
namespace rdhttp {

    HttpServer::HttpServer(boost::asio::io_context& ctx, std::int32_t port, std::string doc_root)
        : ctx(ctx),
          acceptor(ctx),
          doc_root(doc_root),
          port(port) {
        boost::beast::error_code ec;

        // Open the acceptor
        auto endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);
        acceptor.open(endpoint.protocol(), ec);
        if (ec) {
            fail(ec, "open");
            return;
        }

        // Allow address reuse
        acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
        if (ec) {
            fail(ec, "set_option");
            return;
        }

        // Bind to the server address
        acceptor.bind(endpoint, ec);
        if (ec) {
            fail(ec, "bind");
            return;
        }

        // Start listening for connections
        acceptor.listen(
            boost::asio::socket_base::max_listen_connections, ec);
        if (ec) {
            fail(ec, "listen");
            return;
        }

        do_accept();
    }

    HttpServer::~HttpServer() {
    }

    RequestHandler& HttpServer::get(std::string target) {
        return get_handlers[target];
    }
    PosttHandler& HttpServer::post(std::string target) {
        return post_handlers[target];
    }

    void HttpServer::do_accept() {
        acceptor.async_accept(
            [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket) {
                if (!ec) {
                    // 启动一个新的会话来处理客户端连接
                    HttpSession::shared_ptr new_session(new HttpSession(std::move(socket), doc_root, get_handlers, post_handlers));
                    new_session->start();
                }

                // 继续监听新连接
                do_accept();
            });
    }

}  // namespace rdhttp
